import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';

import 'device_screen.dart';
import '../utils/snackbar.dart';
import '../widgets/system_device_tile.dart';
import '../widgets/scan_result_tile.dart';
import '../utils/extra.dart';

class ScanScreen extends StatefulWidget {
  const ScanScreen({super.key});

  @override
  State<ScanScreen> createState() => _ScanScreenState();
}

class _ScanScreenState extends State<ScanScreen> {
  /// 存放从系统 API 获取到的设备列表（例如 `FlutterBluePlus.systemDevices` 返回的结果）。
  /// 这些通常是系统级的已知/配对设备，优先展示给用户。
  List<BluetoothDevice> _systemDevices = [];

  /// 扫描到的设备结果列表（`ScanResult`），用于在界面上展示每个可发现的 BLE 设备。
  List<ScanResult> _scanResults = [];

  /// 当前是否正在执行扫描操作（由 `FlutterBluePlus.isScanning` 更新）。
  /// 用于控制 UI 中扫描按钮的显示状态与进度指示器。
  bool _isScanning = false;

  /// 订阅 `FlutterBluePlus.scanResults` 的订阅对象。
  /// 用于在收到新的扫描结果时更新 `_scanResults` 并触发 UI 刷新。
  late StreamSubscription<List<ScanResult>> _scanResultsSubscription;

  /// 订阅 `FlutterBluePlus.isScanning` 的订阅对象。
  /// 用于接收扫描状态（开始/停止）更新并同步 `_isScanning`。
  late StreamSubscription<bool> _isScanningSubscription;

  @override
  void initState() {
    super.initState();

    _scanResultsSubscription = FlutterBluePlus.scanResults.listen((results) {
      if (mounted) {
        setState(() => _scanResults = results);
      }
    }, onError: (e) {
      Snackbar.show(ABC.b, prettyException("Scan Error:", e), success: false);
    });

    _isScanningSubscription = FlutterBluePlus.isScanning.listen((state) {
      if (mounted) {
        setState(() => _isScanning = state);
      }
    });
  }

  @override
  void dispose() {
    _scanResultsSubscription.cancel();
    _isScanningSubscription.cancel();
    super.dispose();
  }

  Future onScanPressed() async {
    /// 发起系统设备查询并开始 BLE 扫描。
    ///
    /// 行为：首先尝试获取系统设备（iOS 需要指定服务），随后调用 `startScan`。
    try {
      // `withServices` 在 iOS 上出于隐私目的此项是必需的，而在 Android 上此项会被忽略。
      var withServices = [Guid("180f")]; // Battery Level Service
      _systemDevices = await FlutterBluePlus.systemDevices(withServices);
    } catch (e, backtrace) {
      Snackbar.show(ABC.b, prettyException("System Devices Error:", e), success: false);
      print(e);
      print("backtrace: $backtrace");
    }
    try {
      await FlutterBluePlus.startScan(
        timeout: const Duration(seconds: 15),
        webOptionalServices: [ // webOptionalServices：这是给 Web Bluetooth（浏览器）用的，用来向浏览器声明你想访问的 Service，浏览器端需要它来请求权限；在原生 iOS/Android 下这个参数不影响（对 Android 无效，对 iOS 一般也可忽略）
          Guid("180f"), // 电池（Battery）
          Guid("180a"), // 设备信息（Device Info）
          Guid("1800"), // 通用访问（Generic Access）
          Guid("6e400001-b5a3-f393-e0a9-e50e24dcca9e"), // Nordic UART（串口）
        ],
      );
    } catch (e, backtrace) {
      Snackbar.show(ABC.b, prettyException("Start Scan Error:", e), success: false);
      print(e);
      print("backtrace: $backtrace");
    }
    if (mounted) {
      setState(() {});
    }
  }

  Future onStopPressed() async {
    /// 停止扫描。
    try {
      FlutterBluePlus.stopScan();
    } catch (e, backtrace) {
      Snackbar.show(ABC.b, prettyException("Stop Scan Error:", e), success: false);
      print(e);
      print("backtrace: $backtrace");
    }
  }

  void onConnectPressed(BluetoothDevice device) {
    // 连接设备并导航到设备详情页；连接期间 `connectAndUpdateStream` 会更新连接状态流。
    device.connectAndUpdateStream().catchError((e) {
      Snackbar.show(ABC.c, prettyException("Connect Error:", e), success: false);
    });
    MaterialPageRoute route = MaterialPageRoute(
        builder: (context) => DeviceScreen(device: device), settings: RouteSettings(name: '/DeviceScreen'));
    Navigator.of(context).push(route);
  }

  Future onRefresh() {
    if (_isScanning == false) {
      FlutterBluePlus.startScan(timeout: const Duration(seconds: 15));
    }
    if (mounted) {
      setState(() {});
    }
    return Future.delayed(Duration(milliseconds: 500));
  }

  Widget buildScanButton() {
    final button = _isScanning
        ? ElevatedButton(
            onPressed: onStopPressed,
            style: ElevatedButton.styleFrom(
              backgroundColor: Theme.of(context).colorScheme.error,
              foregroundColor: Colors.white,
            ),
            child: const Text("STOP"),
          )
        : ElevatedButton(
            onPressed: onScanPressed,
            style: ElevatedButton.styleFrom(
              backgroundColor: Theme.of(context).primaryColor,
              foregroundColor: Colors.white,
            ),
            child: const Text("SCAN"),
          );

    return Row(
      mainAxisSize: MainAxisSize.min,
      children: [
        if (_isScanning) buildSpinner(),
        button,
      ],
    );
  }

  Widget buildSpinner() {
    return const Padding(
      padding: EdgeInsets.only(right: 20.0),
      child: SizedBox(
        width: 20,
        height: 20,
        child: CircularProgressIndicator(strokeWidth: 2.5),
      ),
    );
  }

  List<Widget> _buildSystemDeviceTiles() {
    return _systemDevices
        .map(
          (d) => SystemDeviceTile(
            device: d,
            onOpen: () => Navigator.of(context).push(
              MaterialPageRoute(
                builder: (context) => DeviceScreen(device: d),
                settings: RouteSettings(name: '/DeviceScreen'),
              ),
            ),
            onConnect: () => onConnectPressed(d),
          ),
        )
        .toList();
  }

  Iterable<Widget> _buildScanResultTiles() {
    return _scanResults
    .where((r) {
        // 只显示设备名称以 'Q' 开头的设备
        final name =
            (r.device.platformName != "" ? r.device.platformName : r.advertisementData.advName);
        return name.toUpperCase().startsWith('Q');
    })
    .map((r) => ScanResultTile(result: r, onTap: () => onConnectPressed(r.device)));
  }

  @override
  Widget build(BuildContext context) {
    return ScaffoldMessenger(
      key: Snackbar.snackBarKeyB,
      child: Scaffold(
        appBar: AppBar(
          title: const Text('扫描列表'),
          actions: [buildScanButton(), const SizedBox(width: 15)],
        ),
        body: RefreshIndicator(
          onRefresh: onRefresh,
          child: ListView(
            children: <Widget>[
              ..._buildSystemDeviceTiles(),
              ..._buildScanResultTiles(),
            ],
          ),
        ),
        // floatingActionButton: buildScanButton(context),
      ),
    );
  }
}
